home *** CD-ROM | disk | FTP | other *** search
- /* StandardGetFolder example
-
- Steve Falkenburg -- MacDTS
-
- This sample uses the new System 7 CustomGetFile routine
- to provide a StandardGetFolder call to be used by applications
- when the user needs to select a folder instead of a file.
-
- It's written in Think C, but should work in MPW if a few #include
- files are added.
-
- The style of the dialog box is taken from the Human Interface note
- on folder selection.
-
- SJF 5/2/92 added check for empty filename and call to MakeFSSpec
- SJF 5/2/92 added check for refcon in filter and hook routines
- SJF 10/30/91 original coding
-
- */
-
- #include <string.h>
- #include <GestaltEqu.h>
- #include <Folders.h>
- #include <Traps.h>
- #include <Script.h>
- #include <Aliases.h>
- #include "trapavail.h"
-
- /* prototypes */
-
- void InitStuff(void);
- Boolean CustomGet(FSSpec *fSpec);
- pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
- pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
- void HitButton(DialogPtr theDlg,short item);
- pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
- void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
- Boolean SameFile(FSSpec *file1,FSSpec *file2);
- Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
- OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
- OSErr MakeCanonFSSpec(FSSpec *fSpec);
- Boolean ShouldHiliteSelect(FSSpec *fSpec);
-
- /* typedefs */
-
- typedef struct {
- StandardFileReply *replyPtr;
- FSSpec oldSelection;
- } SFData, *SFDataPtr;
-
- /* constants */
-
- #define kSelectItem 10
- #define kSFDlg 128
- #define kCanSelectDesktop true
- #define kSelectStrRsrc 128
- #define kDefaultSelectString "\pSelect"
- #define kDeskStrRsrc 129
- #define kDefaultDeskString "\pDesktop"
- #define kSelectKey 's'
-
- /* globals */
-
- Boolean gHasFindFolder;
- FSSpec gDeskFolderSpec;
- Str255 gSelectString;
- Str255 gDesktopFName;
-
- void main(void)
- {
- FSSpec fSpec;
- Boolean good;
-
- InitStuff();
-
- good = CustomGet(&fSpec);
- }
-
-
- /* initialize managers */
-
- void InitStuff(void)
- {
- OSErr err;
- long gResponse;
- Handle strHndl;
-
- MaxApplZone();
- MoreMasters();
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- FlushEvents(everyEvent,0);
- InitCursor();
-
- gHasFindFolder = false;
- if (TrapAvailable(_GestaltDispatch)) {
- err = Gestalt(gestaltFindFolderAttr,&gResponse);
- if (err==noErr)
- gHasFindFolder = (gResponse && (1<<gestaltFindFolderPresent));
- }
-
- strHndl = Get1Resource('STR ',kSelectStrRsrc);
- if (ResError()!=noErr || !strHndl || !*strHndl)
- BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
- else {
- BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
- ReleaseResource(strHndl);
- }
-
- strHndl = Get1Resource('STR ',kDeskStrRsrc);
- if (ResError()!=noErr || !strHndl || !*strHndl)
- BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
- else {
- BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
- ReleaseResource(strHndl);
- }
- }
-
-
- /* do getfile */
-
- Boolean CustomGet(FSSpec *fSpec)
- {
- Point where = {-1,-1};
- SFReply reply;
- DialogPtr theDialog;
- short item;
- StandardFileReply sfReply;
- SFData sfUserData;
- OSErr err;
- Boolean targetIsFolder,wasAliased;
-
- /* initialize user data area */
-
- sfUserData.replyPtr = &sfReply;
- sfUserData.oldSelection.vRefNum = -9999; /* init to ridiculous value */
-
- CustomGetFile(FilterAllFiles,-1,nil,&sfReply,kSFDlg,where,MyDlgHook,
- MyModalFilter,nil,nil,&sfUserData);
-
- if (sfReply.sfGood) {
- err = ResolveAliasFile(&sfReply.sfFile,true,&targetIsFolder,&wasAliased);
- if (err!=noErr)
- return false;
- }
-
- err = FSMakeFSSpec(sfReply.sfFile.vRefNum,sfReply.sfFile.parID,sfReply.sfFile.name,fSpec);
- if (err!=noErr)
- return false;
-
- return sfReply.sfGood;
- }
-
-
- /* this dialog hook checks the contents of the additional edit fields
- when the user selects a file. The focus of the dialog is changed if one
- of the fields is out of range.
- */
-
- pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
- {
- SFDataPtr sfUserData;
- Boolean hiliteButton;
- FSSpec curSpec;
- OSType refCon;
-
- refCon = GetWRefCon(theDlg);
- if (refCon!=sfMainDialogRefCon)
- return item;
-
- sfUserData = (SFDataPtr) userData;
-
- if (item==sfHookFirstCall || item==sfHookLastCall)
- return item;
-
- if (item==sfItemVolumeUser) {
- sfUserData->replyPtr->sfFile.name[0] = '\0';
- sfUserData->replyPtr->sfFile.parID = 2;
- sfUserData->replyPtr->sfIsFolder = false;
- sfUserData->replyPtr->sfIsVolume = false;
- sfUserData->replyPtr->sfFlags = 0;
- item = sfHookChangeSelection;
- }
-
- if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
- BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
- MakeCanonFSSpec(&curSpec);
-
- if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
- GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);
- SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
-
- BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
- }
-
- if (item==kSelectItem)
- item = sfItemOpenButton;
-
- return item;
- }
-
-
- pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
- {
- Boolean evHandled;
- char keyPressed;
- OSType refCon;
-
- refCon = GetWRefCon(theDlg);
- if (refCon!=sfMainDialogRefCon)
- return false;
-
- evHandled = false;
-
- switch (ev->what) {
- case keyDown:
- case autoKey:
- keyPressed = ev->message & charCodeMask;
- if ((ev->modifiers & cmdKey) != 0) {
- switch (keyPressed) {
- case kSelectKey:
- HitButton(theDlg,kSelectItem);
- *itemHit = kSelectItem;
- evHandled = true;
- break;
- }
- }
- break;
- }
-
- return evHandled;
- }
-
-
- void HitButton(DialogPtr theDlg,short item)
- {
- short iType;
- ControlHandle iHndl;
- Rect iRect;
- long fTicks;
-
- GetDItem(theDlg,item,&iType,&iHndl,&iRect);
- HiliteControl(iHndl,inButton);
- Delay(5,&fTicks);
- HiliteControl(iHndl,0);
- }
-
-
- pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
- {
- if (pb->hFileInfo.ioFlAttrib & (1<<4)) /* file is a directory */
- return false;
-
- return true;
- }
-
-
- void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
- {
- ControlHandle selectButton;
- short iType;
- Handle iHndl;
- Rect iRect;
- Str255 storeName,tempLenStr,tempSelName;
- short btnWidth;
-
- BlockMove(selName,tempSelName,selName[0]+1);
- GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
-
- /* truncate select name to fit in button */
-
- btnWidth = iRect.right - iRect.left;
- BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
- p2cstr(tempLenStr);
- strcat((char *)tempLenStr," “” ");
- c2pstr((char *)tempLenStr);
- btnWidth -= StringWidth(tempLenStr);
- TruncString(btnWidth,tempSelName,smTruncMiddle);
-
- BlockMove(gSelectString,storeName,gSelectString[0]+1);
- p2cstr(storeName);
- p2cstr(tempSelName);
- strcat((char *)storeName," “");
- strcat((char *)storeName,(char *)tempSelName);
- strcat((char *)storeName,"”");
-
- c2pstr((char *)storeName);
- c2pstr(tempSelName);
- SetCTitle(iHndl,storeName);
-
- SetDItem(theDlg,kSelectItem,iType,iHndl,&iRect);
-
- if (hilited)
- HiliteControl(iHndl,0);
- else
- HiliteControl(iHndl,255);
- }
-
-
- Boolean SameFile(FSSpec *file1,FSSpec *file2)
- {
- if (file1->vRefNum != file2->vRefNum)
- return false;
- if (file1->parID != file2->parID)
- return false;
- if (!EqualString(file1->name,file2->name,false,true))
- return false;
-
- return true;
- }
-
-
- OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
- {
- DirInfo infoPB;
- OSErr err;
-
- if (!gHasFindFolder) {
- fSpec->vRefNum = -9999;
- return -1;
- }
-
- fSpec->name[0] = '\0';
- err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
- &fSpec->vRefNum,&fSpec->parID);
- if (err!=noErr)
- return err;
-
- return MakeCanonFSSpec(fSpec);
- }
-
-
- Boolean ShouldHiliteSelect(FSSpec *fSpec)
- {
- if (SameFile(fSpec,&gDeskFolderSpec)) {
- BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
- return kCanSelectDesktop;
- }
- else
- return true;
- }
-
-
- OSErr MakeCanonFSSpec(FSSpec *fSpec)
- {
- DirInfo infoPB;
- OSErr err;
-
- if (fSpec->name[0] != '\0')
- return;
-
- infoPB.ioNamePtr = fSpec->name;
- infoPB.ioVRefNum = fSpec->vRefNum;
- infoPB.ioDrDirID = fSpec->parID;
- infoPB.ioFDirIndex = -1;
- err = PBGetCatInfo(&infoPB,false);
- fSpec->parID = infoPB.ioDrParID;
-
- return err;
- }
-
-